package logic

import (
	"context"
	"encoding/json"

	// "fmt"
	"strings"

	"mall/common/cachex"
	"mall/common/globalkey"
	"mall/common/mqueuex"
	"mall/common/resultx"
	"mall/common/utils/pointy"
	"mall/service/blog/model"
	"mall/service/blog/rpc/internal/svc"
	"mall/service/blog/rpc/internal/utils/errorhandler"
	"mall/service/blog/rpc/types/blog"
	"mall/service/user/rpc/userclient"

	// "github.com/sirupsen/logrus"
	"github.com/zeromicro/go-zero/core/logx"
)

type RefreshCacheLogic struct {
	ctx    context.Context
	svcCtx *svc.ServiceContext
	logx.Logger
}

type MediaInfo struct {
	Uid       *uint64 `json:"uid,omitempty"`
	Id        *string `json:"id,omitempty"`
	Thumbnail *uint32 `json:"thumbnail,omitempty"`
	Url       *string `json:"url"`
	Order     *uint32 `json:"order,omitempty"`
}

type KbEntryInfo struct {
	Id       *uint64        `json:"id"`
	Title    *string        `json:"title"`
	Slug     *string        `json:"slug"`
	ImageUrl *string        `json:"imageUrl,omitempty"`
	Year     *string        `json:"year,omitempty"`
	Media    []*MediaInfo   `json:"media,omitempty"`
	Brands   []*KbEntryInfo `json:"brand,omitempty"`
}

func NewRefreshCacheLogic(ctx context.Context, svcCtx *svc.ServiceContext) *RefreshCacheLogic {
	return &RefreshCacheLogic{
		ctx:    ctx,
		svcCtx: svcCtx,
		Logger: logx.WithContext(ctx),
	}
}

// ##25.03.11##
func (l *RefreshCacheLogic) RefreshCache(in *blog.RefreshCacheReq) (*blog.RefreshCacheResp, error) {
	if in.UserId == nil || *in.UserId == 0 {
		return nil, resultx.StatusError(resultx.USER_ID_REQUIRED, "")
	}

	if in.Type == nil || *in.Type == 0 {
		return nil, resultx.StatusError(resultx.REUQEST_PARAM_ERROR, "")
	}

	if in.PlatformId == nil || *in.PlatformId == 0 {
		return nil, resultx.StatusError(resultx.REUQEST_PARAM_ERROR, "")
	}

	cacheType := *in.Type
	var meta []*blog.MetaInfo
	if cacheType >= cachex.ForumNewOwnEntry {
		newMeta, err := l.refreshOwnEntryCache(in)
		if err != nil {
			logx.Errorw("RefreshCache refreshOwnEntryCache err", logx.Field("detail", err.Error()))
			// logrus.Info(fmt.Sprintf("RefreshCache refreshOwnEntryCache err: %+v", err))
		} else {
			meta = append(meta, newMeta...)
		}
		cacheType -= cachex.ForumNewCollectEntry
	}

	return &blog.RefreshCacheResp{
		Meta: meta,
	}, nil
}

func (l *RefreshCacheLogic) refreshOwnEntryCache(in *blog.RefreshCacheReq) (meta []*blog.MetaInfo, err error) {
	userId := *in.UserId
	filterMap := make(map[string]map[string][]any)
	filterMap[model.BlogReactionLogColumns.UserID] = map[string][]any{
		"equalTo": {userId},
	}
	filterMap[model.BlogReactionLogColumns.Type] = map[string][]any{
		"equalTo": {"own"},
	}
	filterMap[model.BlogReactionLogColumns.Status] = map[string][]any{
		"equalTo": {globalkey.StatusEnabled},
	}
	filterMap[model.BlogReactionLogColumns.PostType] = map[string][]any{
		"equalTo": {globalkey.PostTypeKnowledgeBase},
	}

	res, _, err := l.svcCtx.Reaction.GetList(l.ctx, model.M{
		"pageSize": uint64(10),
		"select":   model.BlogReactionLogColumns.PostID,
		"latest":   "1",
	}, -1, filterMap)
	if err != nil {
		return nil, errorhandler.DefaultRepositoryError(l.Logger, err, in)
	}

	if len(res) > 0 {
		var pids []any
		for _, v := range res {
			pids = append(pids, v.PostID)
		}

		entryFilterMap := make(map[string]map[string][]any)
		entryFilterMap[model.BlogKnowledgeBasisColumns.ID] = map[string][]any{
			"in": pids,
		}
		entryFilterMap[model.BlogKnowledgeBasisColumns.SectionID] = map[string][]any{
			"equalTo": {globalkey.TermCategoryTypePerfume},
		}
		entryFilterMap[model.BlogKnowledgeBasisColumns.PostStatus] = map[string][]any{
			"equalTo": {globalkey.PostStatusPublish},
		}

		ret, _, err := l.svcCtx.KBEntry.GetList(l.ctx, model.M{}, -1, entryFilterMap)
		if err != nil {
			return nil, errorhandler.DefaultRepositoryError(l.Logger, err, in)
		}

		if len(ret) > 0 {
			idMetumMap := make(map[uint64][]*model.BlogKnowledgeBaseMetum)
			subFilterMap := make(map[string]map[string][]any)
			subFilterMap[model.BlogKnowledgeBaseMetumColumns.KnowledgeBaseID] = map[string][]any{
				"in": pids,
			}
			subFilterMap[model.BlogKnowledgeBaseMetumColumns.MetaKey] = map[string][]any{
				"in": {"_thumbnail_url", "_year"},
			}
			list, _, err := l.svcCtx.KBEntry.GetMeta(l.ctx, model.M{}, -1, subFilterMap)
			if err != nil {
				return nil, errorhandler.DefaultRepositoryError(l.Logger, err, in)
			}

			if len(list) > 0 {
				for _, v := range list {
					idMetumMap[v.KnowledgeBaseID] = append(idMetumMap[v.KnowledgeBaseID], v)
				}
			}

			var entries []*KbEntryInfo
			for _, v := range ret {
				var mediaUrl *string
				var year *string

				if ms, ok := idMetumMap[v.ID]; ok {
					for _, m := range ms {
						key := strings.TrimSpace(m.MetaKey)
						if len(key) > 0 && m.MetaValue.Valid {
							val := m.MetaValue.String
							switch key {
							case "_thumbnail_url":
								mediaUrl = pointy.GetPointer(val)
							case "_year":
								year = pointy.GetPointer(val)
							}
						}
					}
				}

				entries = append(entries, &KbEntryInfo{
					Id:       &v.ID,
					Title:    &v.PostTitle,
					Slug:     &v.PostName,
					ImageUrl: mediaUrl,
					Year:     year,
				})
			}

			ownEntryItems, err := json.Marshal(entries)
			if err != nil {
				// logrus.Info(fmt.Sprintf("RefreshCache refreshOwnEntryCache json.Marshal err: %+v", err))
				logx.Errorw("RefreshCache refreshOwnEntryCache err", logx.Field("detail", err.Error()))
				return nil, err
			}

			var userMeta []*userclient.UserMetaInfo
			userMeta = append(userMeta, &userclient.UserMetaInfo{
				Key:   pointy.GetPointer(mqueuex.UserStatisticOwnEntryNew), // "_own_entry_status"
				Value: pointy.GetPointer("1"),
			})
			userMeta = append(userMeta, &userclient.UserMetaInfo{
				Key:   pointy.GetPointer(mqueuex.UserCacheOwnEntry), // "_own_entry_items"
				Value: pointy.GetPointer(string(ownEntryItems)),
			})
			_, err = l.svcCtx.UserRpc.SetUserMeta(l.ctx, &userclient.SetUserMetaReq{
				UserId:   pointy.GetPointer(userId),
				UserMeta: userMeta,
			})
			if err != nil {
				// logrus.Info(fmt.Sprintf("RefreshCache refreshOwnEntryCache UserRpc.SetUserMeta err: %+v", err))
				logx.Errorw("RefreshCache refreshOwnEntryCache err", logx.Field("detail", err.Error()))
				return nil, err
			}

			meta = append(meta, &blog.MetaInfo{
				Id:    pointy.GetPointer(userId),
				Key:   pointy.GetPointer("ownEntryItems"),
				Value: pointy.GetPointer(string(ownEntryItems)),
			})
		}
	}

	return
}
